home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 11 / FM Towns Free Software Collection 11.iso / t_os / tool / artemis1 / src / colchg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-14  |  10.2 KB  |  449 lines

  1. /*
  2.     colchg.c
  3. */
  4.  
  5. #include <stdlib.h>
  6. #include <stdlib.h>
  7. #include <math.h>
  8.  
  9. #include "ge.h"
  10. #include "imageman.h"
  11. #include "dispman.h"
  12. #include "mainmenu.h"
  13.  
  14.  
  15. static int cmat[3][4];
  16.  
  17.  
  18. static int colchg_init(int c1,int c2,int mode)
  19. {
  20. #define    F(a)    (int)((a)*65536.0)
  21.     int r1,g1,b1,r2,g2,b2;
  22.     double n1,n2,n3,l;
  23.     double cos_t,sin_t,l1,l2;
  24.     // 2色をRGB要素に分解
  25.     r1=getR(c1),g1=getG(c1),b1=getB(c1);
  26.     r2=getR(c2),g2=getG(c2),b2=getB(c2);
  27.     l1 = sqrt((double)(r1*r1+g1*g1+b1*b1));
  28.     l2 = sqrt((double)(r2*r2+g2*g2+b2*b2));
  29.     // C1からC2へ回転するときの軸を算出 (C1,C2の外積) → (n1,n2,n3)
  30.     // 回転する角度の余弦・正弦を算出 → cos_t, sin_t
  31.     n1=g1*b2-b1*g2, n2=b1*r2-r1*b2, n3=r1*g2-g1*r2;
  32.     l=sqrt(n1*n1+n2*n2+n3*n3);
  33.     if (l == 0)
  34.     {
  35.         n1 = 1.0, n2 = n3 = 0.0;
  36.         cos_t=1.0, sin_t=0.0;
  37.     }
  38.     else
  39.     {
  40.         n1=n1/l, n2=n2/l, n3=n3/l;
  41.         if (l1 == 0 || l2 == 0)
  42.             return -1;
  43.         cos_t = (double)(r1*r2+g1*g2+b1*b2) / (l1 * l2);
  44.         if (cos_t <= 0.0)
  45.             cos_t = 0.0;
  46.         else if (cos_t > 1.0)
  47.             cos_t = 1.0;
  48.         sin_t = sqrt(1-cos_t*cos_t);
  49.     }
  50.     if (mode == 0)
  51.     {    // ★直交変換のみによる変換
  52.         // スケーリング値を算出
  53.         double k;
  54.         if (l1 == 0.0)
  55.             k = (l2 == 0.0 ? 1.0 : 50.0);    // RGB各5ビットなので50で十分
  56.         else
  57.             k = l2 / l1;
  58.         // 変換行列を作成
  59.         double p = 1-cos_t;
  60.         cmat[0][0] = F(k * (p*n1*n1+cos_t));
  61.         cmat[0][1] = F(k * (p*n1*n2-n3*sin_t));
  62.         cmat[0][2] = F(k * (p*n1*n3+n2*sin_t));
  63.         cmat[0][3] = 0;
  64.         cmat[1][0] = F(k * (p*n1*n2+n3*sin_t));
  65.         cmat[1][1] = F(k * (p*n2*n2+cos_t));
  66.         cmat[1][2] = F(k * (p*n2*n3-n1*sin_t));
  67.         cmat[1][3] = 0;
  68.         cmat[2][0] = F(k * (p*n1*n3-n2*sin_t));
  69.         cmat[2][1] = F(k * (p*n2*n3+n1*sin_t));
  70.         cmat[2][2] = F(k * (p*n3*n3+cos_t));
  71.         cmat[2][3] = 0;
  72.     }
  73.     else if (mode == 1)
  74.     {    // ★直交変換+平行移動による変換(2色の明るさがほぼ同じ場合によい)
  75.         if (l2 == 0.0)
  76.             goto mode2;
  77.         // 回転後に平行移動する変位を算出
  78.         double m1,m2,m3;
  79.         m1=r2/l2,m2=g2/l2,m3=b2/l2;
  80.         m1 *= (l2-l1), m2 *= (l2-l1), m3 *= (l2-l1);
  81.         // 変換行列を作成
  82.         double p = 1-cos_t;
  83.         cmat[0][0] = F(p*n1*n1+cos_t);
  84.         cmat[0][1] = F(p*n1*n2-n3*sin_t);
  85.         cmat[0][2] = F(p*n1*n3+n2*sin_t);
  86.         cmat[0][3] = F(m1);
  87.         cmat[1][0] = F(p*n1*n2+n3*sin_t);
  88.         cmat[1][1] = F(p*n2*n2+cos_t);
  89.         cmat[1][2] = F(p*n2*n3-n1*sin_t);
  90.         cmat[1][3] = F(m2);
  91.         cmat[2][0] = F(p*n1*n3-n2*sin_t);
  92.         cmat[2][1] = F(p*n2*n3+n1*sin_t);
  93.         cmat[2][2] = F(p*n3*n3+cos_t);
  94.         cmat[2][3] = F(m3);
  95.     }
  96.     else if (mode == 2)
  97.     {    // ★平行移動のみによる変換(2色がよく似た色の場合によい)
  98. mode2:
  99.         cmat[0][0] = F(1);
  100.         cmat[0][1] = 0;
  101.         cmat[0][2] = 0;
  102.         cmat[0][3] = F((double)(r2-r1));
  103.         cmat[1][0] = 0;
  104.         cmat[1][1] = F(1);
  105.         cmat[1][2] = 0;
  106.         cmat[1][3] = F((double)(g2-g1));
  107.         cmat[2][0] = 0;
  108.         cmat[2][1] = 0;
  109.         cmat[2][2] = F(1);
  110.         cmat[2][3] = F((double)(b2-b1));
  111.     }
  112.     else if (mode == 3)
  113.     {
  114.         // ★RGB各要素に定数を掛ける変換(特定要素を強調したい/弱めたいときによい)
  115.         cmat[0][0] = (r1>0 ? F((double)r2/(double)r1) : r2 > 0 ? F(50) : 0);
  116.         cmat[0][1] = 0;
  117.         cmat[0][2] = 0;
  118.         cmat[0][3] = 0;
  119.         cmat[1][0] = 0;
  120.         cmat[1][1] = (g1>0 ? F((double)g2/(double)g1) : g2 > 0 ? F(50) : 0);
  121.         cmat[1][2] = 0;
  122.         cmat[1][3] = 0;
  123.         cmat[2][0] = 0;
  124.         cmat[2][1] = 0;
  125.         cmat[2][2] = (b1>0 ? F((double)b2/(double)b1) : b2 > 0 ? F(50) : 0);
  126.         cmat[2][3] = 0;
  127.     }
  128.     return 0;
  129. #undef    F
  130. }
  131.  
  132.  
  133. static int colchg_trans(int c)
  134. {
  135.     int r0,g0,b0,r,g,b;
  136.     r0=getR(c),g0=getG(c),b0=getB(c);
  137.     r = (cmat[0][0]*r0 + cmat[0][1]*g0 + cmat[0][2]*b0
  138.          + cmat[0][3] + 0x8000) >> 16;
  139.     g = (cmat[1][0]*r0 + cmat[1][1]*g0 + cmat[1][2]*b0
  140.          + cmat[1][3] + 0x8000) >> 16;
  141.     b = (cmat[2][0]*r0 + cmat[2][1]*g0 + cmat[2][2]*b0
  142.          + cmat[2][3] + 0x8000) >> 16;
  143.     r = _lim(r,0,31);
  144.     g = _lim(g,0,31);
  145.     b = _lim(b,0,31);
  146.     return GRB(g,r,b);
  147. }
  148.  
  149.  
  150. static void colchg_hline(int x1,int x2,int y)
  151. {
  152.     char *dp0 = EIMadrs(x1,y), *sp0 = EIMadrs_back(x1,y);
  153.     void hline(int _x1, int _x2, int _y)
  154.     {
  155.         short *dp = (short*)dp0 + _x1 - x1, *sp = (short*)sp0 + _x1 - x1;
  156.         for (int i=_x1; i<=_x2; i++,dp++,sp++)
  157.             *dp = colchg_trans(*sp);
  158.     }
  159.     hline_func(x1,x2,y,hline);
  160.     DMimage_hline_map(x1,x2,y,dp0);
  161. }
  162.  
  163. static void mono_hline(int x1,int x2,int y)
  164. {
  165.     char *dp0 = EIMadrs(x1,y), *sp0 = EIMadrs_back(x1,y);
  166.     void hline(int _x1, int _x2, int _y)
  167.     {
  168.         short *dp = (short*)dp0 + _x1 - x1, *sp = (short*)sp0 + _x1 - x1;
  169.         for (int i=_x1; i<=_x2; i++,dp++,sp++)
  170.         {
  171.             int sc = *sp;
  172.             int r=getR(sc),g=getG(sc),b=getB(sc);
  173.             int dg = (306*r+601*g+117*b+512)>>10;
  174.             *dp = GRB(dg,dg,dg);
  175.         }
  176.     }
  177.     hline_func(x1,x2,y,hline);
  178.     DMimage_hline_map(x1,x2,y,dp0);
  179. }
  180.  
  181.  
  182. static void colchg(int col1,int col2,int method,int a)
  183. // a:0=色彩変換  1=モノクロ化
  184. {
  185.     int ax1,ay1,ax2,ay2;
  186.     area_getboundxy(&ax1,&ay1,&ax2,&ay2);
  187.     int x,y;
  188.     if (a == 0)
  189.     {
  190.         if (colchg_init(col1,col2,method) != 0)
  191.             return;
  192.     }
  193.     for (y=ay1; y<=ay2; y++)
  194.     {
  195.         x = ax1 + area_chkxylen(ax1,ax2,y,YES);
  196.         while (x<=ax2)
  197.         {
  198.             int l;
  199.             if ((l = area_chkxylen(x,ax2,y,NO)) == 0)
  200.                 break;
  201.             if (a == 0)
  202.                 colchg_hline(x,x+l-1,y);
  203.             else
  204.                 mono_hline(x,x+l-1,y);
  205.             x += l + area_chkxylen(x+l,ax2,y,YES);
  206.         }
  207.     }
  208. }
  209.  
  210.  
  211. static void do_colchg(int col1, int col2, int method)
  212. {
  213.     bool first = YES;
  214.     for (;;)
  215.     {
  216.         if (area_input(AREA_POLYGON) != 0)
  217.             break;
  218.         if (first)
  219.             { EIMbackup();  first = NO; }
  220.         colchg(col1,col2,method,0);
  221.     }
  222. }
  223.  
  224.  
  225. static void do_mono()
  226. {
  227.     for (;;)
  228.     {
  229.         if (area_input(AREA_POLYGON) != 0)
  230.             break;
  231.         EIMbackup();
  232.         colchg(0,0,0,1);
  233.     }
  234. }
  235.  
  236. /*--------------------------------------------------------*/
  237. /*                 色彩変換メニューの定義                 */
  238. /*--------------------------------------------------------*/
  239.  
  240. static int col1,col2;
  241. static int method = 0;
  242.  
  243. #define    MYLEN    256
  244.  
  245. /*
  246. #define    itemExec    1
  247. #define    itemCancel    2
  248. #define    itemCol1    4
  249. #define    itemCol2    6
  250. #define    itemColList    8
  251. #define    itemRgbBar    9
  252. #define    itemMethod    11
  253. #define    itemHelp    12
  254. #define    itemCmdMono    13
  255. */
  256.  
  257. static void disp_colchgmenu(), erase_colchgmenu();
  258.  
  259. #include "colchg.md"
  260.  
  261. static char *help[] = {
  262. "[標準変換]\n\
  263. RGB 空間での回転+スカラー倍による変換。たいていはこれでこと足りる。",
  264. "[グラデ保存変換]\n\
  265. RGB 空間での回転+平行移動による変換。\
  266. 微妙なグラデーションを壊したくないときによい。",
  267. "[ちょびっと変換]\n\
  268. RGB 空間での平行移動のみによる変換。わずかな色彩変更のときによい。",
  269. "[RGB 掛け算変換]\n\
  270. RGB 各要素についての色1,色2 の比を全色に掛ける。\
  271. 特定の色要素を強(弱)めたいときによい。"
  272. };
  273.  
  274. static void disp_methodhelp(int m)
  275. {
  276.     int ix,iy,ixlen,iylen;
  277.     menu_getbuttonxy(&colchgmenu, itemHelp, &ix, &iy, &ixlen, &iylen);
  278.     grboxfill(ix,iy,ixlen,iylen,DMgetmenuplt(White),DrawNORMAL);
  279.     ix+=4,ixlen-=16;
  280.     iy+=4,iylen-=8;
  281.     putmsg_width(ix,iy,ixlen,help[m],DMgetmenuplt(Black));
  282. }
  283.  
  284. static void draw_csrs(),erase_csrs();
  285.  
  286. static void disp_colchgmenu()
  287. {
  288.     int ix,iy;
  289.     menu_getbuttonxy(&colchgmenu, itemColList, &ix, &iy, NULL, NULL);
  290.     drawPltList(ix,iy);
  291.     drawPltCsr(pltnum);
  292.     cols_init(&col1,&col2, &colchgmenu, itemCol1, itemCol2);
  293.     drawCols();
  294.     drawColCsr();
  295.     draw_csrs();
  296.     disp_methodhelp(menu_selector_getvar(menu_selector(&colchgmenu,selMethod)));
  297. }
  298.  
  299. static void erase_colchgmenu()
  300. {
  301.     eraseCols();
  302.     erasePltList();
  303. }
  304.  
  305. static void draw_csrs_sub(int col)
  306. {
  307. #if 0
  308.     // 変換方法カーソルの描画
  309.     int ix,iy;
  310.     menu_getbuttonxy(&colchgmenu, itemMethod, &ix, &iy, NULL, NULL);
  311.     grboxline(ix+24*method-4,iy-2,24,16+4,DMgetmenuplt(col),DrawNORMAL);
  312. #endif
  313. }
  314.  
  315. static void draw_csrs()
  316. {
  317.     draw_csrs_sub(Black);
  318. }
  319.  
  320. static void erase_csrs()
  321. {
  322.     draw_csrs_sub(COL_menu);
  323. }
  324.  
  325. void commandColchg()
  326. {
  327.     static bool first = YES;
  328.     if (first)
  329.         col1 = forecol, col2 = backcol, method = 0;
  330.     first = NO;
  331.     menu_disp(&colchgmenu);
  332.     for (;;)
  333.     {
  334.         DMdispcsr(ms.x,ms.y);
  335.         for (;;)
  336.         {
  337.             ms_get(&ms);
  338.             if (ms.dx!=0||ms.dy!=0||ms.btn1!=OFF||ms.btn2!=OFF||key_chk()!=0)
  339.                 break;
  340.         }
  341.         DMerasecsr();
  342.         scrollForCsr(1,1);
  343.         if (ms.btn1 == OFFON)
  344.         {
  345.             int a; int ax,ay;
  346.             a = menu_where(ms.x,ms.y,&colchgmenu, &ax,&ay,NULL);
  347.             switch (a)
  348.             {
  349.             case itemExec:
  350.                 menu_erase();
  351.                 do_colchg(col1,col2,menu_selector_getvar(menu_selector(&colchgmenu,selMethod)));
  352.                 goto end;
  353.             case itemCancel:
  354.                 goto exitloop;
  355.             case itemCol1:
  356.             case itemCol2:
  357.                 drawColCsr();
  358.                 cols_setcsrpos((a==itemCol1 ? 0 : 1));
  359.                 drawColCsr();
  360.                 break;
  361.             case itemColList:
  362.                 drawPltCsr(pltnum);    // erase
  363.                 pltnum = ax/16 + (ay/16)*4;
  364.                 makeupRgbBar();
  365.                 drawPltCsr(pltnum);    // draw
  366.                 if (cols_getcsrpos() == 0)
  367.                     col1 = plt_getcode(pltnum);
  368.                 else
  369.                     col2 = plt_getcode(pltnum);
  370.                 makeupCols();
  371.                 break;
  372.             case itemRgbBar:
  373.                 touchRgbBar(ax,ay,ms.btn1);
  374.                 if (cols_getcsrpos() == 0)
  375.                     col1 = plt_getcode(pltnum);
  376.                 else
  377.                     col2 = plt_getcode(pltnum);
  378.                 makeupCols();
  379.                 break;
  380.             case itemMethod:
  381.                 erase_csrs();
  382.                 method = ax / 24;
  383.                 // disp_methodhelp(0);
  384.                 draw_csrs();
  385.                 break;
  386.             case itemCmdMono:
  387.                 menu_erase();
  388.                 do_mono();
  389.                 goto end;
  390.             case itemMoveMenu:
  391.                 menu_move();
  392.                 break;
  393.             case itemSelector:
  394.                 menu_touchselector(&colchgmenu);
  395.                 disp_methodhelp(menu_selector_getvar(menu_selector(&colchgmenu,selMethod)));
  396.                 break;
  397.             }
  398.         }
  399.         else if (ms.btn1 == ON)
  400.         {
  401.             int a; int ax,ay;
  402.             a = menu_where(ms.x,ms.y,&colchgmenu, &ax,&ay,NULL);
  403.             switch (a)
  404.             {
  405.             case itemRgbBar:
  406.                 touchRgbBar(ax,ay,ms.btn1);
  407.                 if (cols_getcsrpos() == 0)
  408.                     col1 = plt_getcode(pltnum);
  409.                 else
  410.                     col2 = plt_getcode(pltnum);
  411.                 makeupCols();
  412.             }
  413.         }
  414.         if (ms.btn2 == OFFON)
  415.         {
  416.             int a;
  417.             a = menu_where(ms.x,ms.y,&colchgmenu, NULL,NULL,NULL);
  418.             if (a == OutOfMenu)
  419.             {
  420.                 int px,py;
  421.                 px = DMimage_getx(ms.x),  py = DMimage_gety(ms.y);
  422.                 drawPltCsr(pltnum);    // erase
  423.                 if (mode == MODE32K)
  424.                     plt_setcode(pltnum, EIMpoint(px,py));
  425.                 else
  426.                     pltnum = EIMpoint(px,py);
  427.                 makeupPltList();
  428.                 makeupRgbBar();
  429.                 drawPltCsr(pltnum);    // draw
  430.                 drawColCsr();  // erase
  431.                 if (cols_getcsrpos() == 0)
  432.                     col1 = plt_getcode(pltnum);
  433.                 else
  434.                     col2 = plt_getcode(pltnum);
  435.                 makeupCols();
  436.                 drawColCsr();    // draw
  437.             }
  438.             else
  439.                 break;
  440.         }
  441.     }
  442. exitloop:
  443.     forecol = (cols_getcsrpos() == 0 ? col1 : col2);
  444.     cols_setcsrpos(0);
  445.     menu_erase();
  446. end:
  447.     return;
  448. }
  449.